package mashibing.freshman.class02;

/**
 * @author: Shelly
 * @create: 2023-01-04 18:45:31
 * @describe:
 */
public class Code02_RandToRand {
    public static void main(String[] args) {
        // random() double [0,1) 等概率返回一个数
        // 数学做不到等概率，但计算机有精度，可以做到，是有穷个数
        System.out.println(Math.random());
        System.out.println("======================");
        // 1、测试等概率
        int testTimes = 10000000;// 1千万测试次数
        int count = 0;
        for (int i = 0; i < testTimes; i++) {
            if (Math.random() < 0.75) {// 0.3
                count++;
            }
        }
        System.out.println((double) count / (double) testTimes);

        System.out.println("=========");
        // 2、0~8上返回
        // [0,1) -> [0,8)
        count = 0;
        for (int i = 0; i < testTimes; i++) {
            if (Math.random() * 8 < 5) {// 八分之五
                count++;
            }
        }
        System.out.println((double) count / (double) testTimes);
        System.out.println((double) 5 / (double) 8);

        // 3、整数范围
        int K = 9;
        // [0,K) -> [0,8]
        int[] counts = new int[9];
        for (int i = 0; i < testTimes; i++) {
            int ans = (int) (Math.random() * K); // [0,K-1]
            counts[ans]++;// 词频统计
        }
        for (int i = 0; i < K; i++) {
            System.out.println(i + "这个数，出现了 " + counts[i] + " 次");
        }

        System.out.println("=========");
        count = 0;
        double x = 0.17;
        for (int i = 0; i < testTimes; i++) {
            if (xToXPower2() < x) {
                count++;
            }
        }
        System.out.println((double) count / (double) testTimes);
        System.out.println(Math.pow(x,2));

        System.out.println("=========");
        count = 0;
        x = 0.17;
        for (int i = 0; i < testTimes; i++) {
            if (xToXPower3() < x) {
                count++;
            }
        }
        System.out.println((double) count / (double) testTimes);
        System.out.println(Math.pow(x,3));

        System.out.println("==等概率返回0和1========");
        count = 0;
        for (int i = 0; i < testTimes; i++) {
            if (f2() == 0) {
                count++;
            }
        }
        System.out.println((double) count / (double) testTimes);

        System.out.println("==等概率返回1 ~ 7========");
        counts = new int[8];
        for (int i = 0; i < testTimes; i++) {
            int num = g();
            counts[num]++;
        }
        for (int i = 0; i < 8; i++) {
            System.out.println(i + "这个数，出现了 " + counts[i] + " 次");
        }


        System.out.println("==01不等概率随机到01等概率随机========");
        counts = new int[2];
        for (int i = 0; i < testTimes; i++) {
            int num = y();
            counts[num]++;
        }
        for (int i = 0; i <= 1; i++) {
            System.out.println(i + "这个数，出现了 " + counts[i] + " 次");
        }
    }

    // 返回[0,1)的一个小数
    // 任意的x，x属于[0,1)，[0,x)范围上的数出现概率由原来的x调整成x平方
    public static double xToXPower2() {
        return Math.max(Math.random(), Math.random());
    }

    // 返回[0,1)的一个小数
    // 任意的x，x属于[0,1)，[0,x)范围上的数出现概率由原来的x调整成x立方
    public static double xToXPower3() {
        return Math.max(Math.random(), Math.max(Math.random(), Math.random()));
    }

    /**如何用1~5的随机函数加工出1~7的随机函数****************************************************************************/
    // lib里的，不能改！
    public static int f1() {
        return (int) (Math.random() * 5) + 1;
    }

    // 随机机制，只能用f1，
    // 等概率返回0和1
    public static int f2() {
        int ans = 0;
        do {
            ans = f1();
        } while (ans == 3);
        return ans < 3 ? 0 : 1;
    }

    // 得到000 ~ 111 做到等概率 0 ~ 7等概率返回一个
    public static int f3() {
        return (f2() << 2) + (f2() << 1) + f2();
    }

    // 0 ~ 6等概率返回一个
    public static int f4() {
        int ans = 0;
        do {
            ans = f3();
        } while (ans == 7);
        return ans;
    }

    // 1~7 等概率返回一个
    public static int g() {
        return f4() + 1;
    }

    /**01不等概率随机到01等概率随机****************************************************************************/
    // 你只能知道，x会以固定概率返回0和1，但是x的内容，你看不到！
    public static int x() {
        return Math.random() < 0.84 ? 0 : 1;
    }

    // 等概率返回0和1
    // 用例子来看
    public static int y() {
        int ans = 0;
        do {
            ans = x();
        } while (ans == x());// 0 0 、 1 1 重做
        // 出来
        // ans = 0 1
        // ans = 1 0
        return ans;
    }
}
